﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using NDimArrayNamespace;

namespace NDimArrayTestProject
{
    [TestClass]
    public class NDimArrayTest
    {
        [TestMethod]
        public void ConstructorTest()
        {
            var ar1 = new NDimArray<int>(3, 3);
            var ar2 = new NDimArray<int>(new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0}, 3, 3);
            
            Assert.AreEqual(ar1, ar2);

            Assert.AreEqual(new NDimArray<int>(3, 4, 3), new NDimArray<int>(3, 4, 3));
        }

        [TestMethod]
        public void ConcatenateTest()
        {
            var ar1 = new NDimArray<int>(new int[] { 1, 1, 1, 1 }, 2, 2);
            var ar2 = new NDimArray<int>(new int[] { -1, -1, -1, -1 }, 2, 2);
            var ar3 = new NDimArray<int>(new int[] { 2, 2, 2, 2 }, 2, 2);

            var cat1 = NDimArray<int>.Concatenate(0, ar1, ar2, ar3);
            var cat2 = NDimArray<int>.Concatenate(2, ar1, ar2, ar3);
            var cat3 = NDimArray<int>.Concatenate(3, ar1, ar2, ar3);

            Assert.AreEqual(
                new NDimArray<int>(new int[] { 1, 1, -1, -1, 2, 2, 1, 1, -1, -1, 2, 2 }, 6, 2),
                cat1);
            Assert.AreEqual(
                new NDimArray<int>(new int[] { 1, 1, 1, 1, -1, -1, -1, -1, 2, 2, 2, 2 }, 2, 2, 3),
                cat2);
            Assert.AreEqual(
               new NDimArray<int>(new int[] { 1, 1, 1, 1, -1, -1, -1, -1, 2, 2, 2, 2 }, 2, 2, 1, 3),
               cat3);
        }

        [TestMethod]
        public void IndexerTest()
        {
            //  ar dimenzija 2 x 3 x 2
            //  ar = [ [0, 1], [2, 3], [ 4,  5] ],
            //       [ [6, 7], [8, 9], [10, 11] ]
            var ar = new NDimArray<int>(new int[] {0,1,2,3,4,5,6,7,8,9,10,11}, 2, 3, 2);

            Assert.AreEqual(3, ar[1, 1, 0]);
            Assert.AreEqual(0, ar[0, 0, 0]);
            Assert.AreEqual(11, ar[1, 2, 1]);

            ar[1, 1, 1] = -9;

            Assert.AreEqual(-9, ar[1, 1, 1]);

            // resizing!
            ar[2, 4, 2] = -15;
 
            // ar dimenzija 3 x 5 x 3
            // ar = [ [0, 1, 0], [2,  3, 0], [ 4,  5, 0], [0, 0, 0], [0, 0,   0] ],
            //      [ [6, 7, 0], [8, -9, 0], [10, 11, 0], [0, 0, 0], [0, 0,   0] ],
            //      [ [0, 0, 0], [0,  0, 0], [ 0,  0, 0], [0, 0, 0], [0, 0, -15] ]
            Assert.AreEqual(
                new NDimArray<int>(new int[] { 0, 1, 0, 2,  3, 0,  4,  5, 0, 0, 0, 0, 0, 0,   0,
                                               6, 7, 0, 8, -9, 0, 10, 11, 0, 0, 0, 0, 0, 0,   0,
                                               0, 0, 0, 0,  0, 0,  0,  0, 0, 0, 0, 0, 0, 0, -15}, 3, 5, 3),
                ar);
        }

        [TestMethod]
        public void SmallDimensionTest()
        {
            // one = [ 2 ]
            var one = new NDimArray<int>(new int[] { 2 }, 1);

            Assert.AreEqual(2, one[0]);

            // one = [ -2 ]
            one[0] = -2;

            Assert.AreEqual(-2, one[0]);

            // one = [ [-2,  0],
            //         [ 0, -9] ]
            one[1, 1] = -9;

            Assert.AreEqual(-9, one[1, 1]);
            Assert.AreEqual(
                new NDimArray<int>(new int[] { -2, 0, 0, -9 }, 2, 2),
                one);

            // one = [ [-2,  0]
            //       [ [ 8, -9] ]
            one[0, 1] = 8;

            Assert.AreEqual(
                new NDimArray<int>(new int[] { -2, 0, 8, -9 }, 2, 2),
                one);
        }

        [TestMethod]
        public void NDimArraySliceTest()
        {
            //  ar dimenzija 3 x 3
            //  ar = [ [0, 1, 2], 
            //         [3, 4, 5],
            //         [6, 7, 8] ]
            var ar = new NDimArray<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8}, 3, 3);

            // sl dimenzija 2 x 2
            // sl(ar) = [ [0, 2],
            //            [6, 8] ]
            var sl = new NDimArraySlice<int>(ar, new int[][] { new int[] {0, 2}, new int[] {0, 2}});

            Assert.AreEqual(8, sl[1, 1]);

            sl[0, 1] = 9;

            Assert.AreEqual(9, sl[0, 1]);

            for (int i = 0; i < sl.ElementCount; ++i)
                sl[sl.PositionToCoordinates(i)] = sl[sl.PositionToCoordinates(i)] + 1;

            Assert.AreEqual(1, sl[0, 0]);
            Assert.AreEqual(3, sl[1, 0]);
            Assert.AreEqual(10, sl[0, 1]);
            Assert.AreEqual(9, sl[1, 1]);
        }

        [TestMethod]
        public void SubArrayTest()
        {
            //  ar dimenzija 3 x 3
            //  ar = [ [0, 1, 2], 
            //         [3, 4, 5],
            //         [6, 7, 8] ]
            var ar = new NDimArray<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 3, 3);

            // sub dimenzija 2 x 2
            // sub = [ [0, 2], [6, 8] ]
            var sub = ar.GetSubNDimArray(new int[][] { new int[] { 0, 2 }, new int[] { 0, 2 } });

            var exp = new NDimArray<int>(new int[] { 0, 2, 6, 8 }, 2, 2);

            Assert.AreEqual(exp, sub);
        }

        [TestMethod]
        public void AssignTest()
        {
            //  ar dimenzija 3 x 3
            //  ar = [ [0, 1, 2], 
            //         [3, 4, 5],
            //         [6, 7, 8] ]
            var ar = new NDimArray<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 3, 3);

            // sm dimezija 2 x 2
            // sm = [ [-1, -2] [-3, -4] ]
            var sm = new NDimArray<int>(new int[] { -1, -2, -3, -4 }, 2, 2);

            // exp dimenzija 3 x 3
            // exp = [ [-1, 1, -2], [3, 4, 5], [-3, 7, -4] ]
            var exp = new NDimArray<int>(new int[] { -1, 1, -2, 3, 4, 5, -3, 7, -4 }, 3, 3);

            Assert.AreEqual(exp, ar.SubscriptedAssignment(sm, new int[][] { new int[] {0, 2}, new int[] {0, 2}} ));
        }

        [TestMethod]
        public void AssignTest2()
        {
            //  ar dimenzija 3 x 3
            //  ar = [ [0, 1, 2], 
            //         [3, 4, 5],
            //         [6, 7, 8] ]
            var ar = new NDimArray<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, 3, 3);

            // sm dimezija 2 x 2
            // sm = [ [-1, -2] [-3, -4] ]
            var sm = new NDimArray<int>(new int[] { -1, -2, -3, -4 }, 2, 2);

            // exp dimenzija 4 x 4
            // exp = [ [-1, 1, 2, -2], [3, 4, 5, 0], [6, 7, 8, 0], [-3, 0, 0, -4] ]
            var exp = new NDimArray<int>(new int[] { -1, 1, 2, -2, 3, 4, 5, 0, 6, 7, 8, 0, -3, 0, 0, -4 }, 4, 4);

            var result = ar.SubscriptedAssignment(sm, new int[][] { new int[] { 0, 3 }, new int[] { 0, 3 } });
            Assert.AreEqual(exp, result);
        }
    }
}
